package com.conan.app.dailyflickr.activity;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Random;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;

import com.conan.app.flickrdaily.R;
import com.conan.app.dailyflickr.App;
import com.conan.app.dailyflickr.AppData;
import com.conan.app.dailyflickr.app.ApplicationUtils;
import com.conan.app.dailyflickr.app.DailyPhotoData;
import com.conan.app.dailyflickr.provider.ProviderUtils;
import com.conan.app.dailyflickr.provider.ProviderUtils.DailyInfo;
import com.conan.app.dailyflickr.provider.ProviderUtils.LayoutType;

public class DailyFlickrWidget extends AppWidgetProvider{
    private static final String TAG = "DailyFlickrWidget";
    public  static HashMap<Integer, DailyInfo> sDailyInfos = new HashMap<Integer, DailyInfo>();
    // private int[] demos = {R.drawable.demo_0, R.drawable.demo_1, R.drawable.demo_2 };

    @Override
    public void onEnabled(Context context) {
        // This is only called once, regardless of the number of widgets of this type
        // We do not have any global initialization
        Log.i(TAG, "onEnabled()");
        super.onEnabled(context);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Log.i(TAG, "---------------	onUpdate() ------------- " );
        if(appWidgetIds == null) {
            appWidgetIds = appWidgetManager.getAppWidgetIds(
                    new ComponentName(context, DailyFlickrWidget.class));
        }

        Calendar date = Calendar.getInstance(Locale.US);
        date.add(Calendar.DATE, -2);
        DailyInfo info;

        // Random ran = new Random();
        for(int appWidgetId : appWidgetIds) {
            info = ProviderUtils.getWidgetInfoFromProvider(context, appWidgetId);
            info._page = 1;
            info._date = date;
            // update map widget info data
            sDailyInfos.put(appWidgetId, info);	
            Log.d(TAG, "onUpdate() ---- " + appWidgetId);
            
            // Get the layout for the App Widget and attach an on-click listener to the button
            RemoteViews remoteView = getRemoteView(context, info,  
                    context.getResources().getString(R.string.loading));
            remoteView.setImageViewResource(R.id.imv_main_img_of_dailyflickr_id, 
                    R.drawable.no_image);
            remoteView.setTextViewText(R.id.tv_main_message_date_id,  
                    ApplicationUtils.buildDateString(info._date.getTime()));

            setControlEvent(context, remoteView, appWidgetId);

            appWidgetManager.updateAppWidget(appWidgetId, remoteView);

            // Tell the AppWidgetManager to perform an update on the current app widget
            // appWidgetManager.updateAppWidget(appWidgetId, remoteView);
            // update provider --> will do in method ...
            startServiceUpdateAppWidget(context, appWidgetId,  
                    AppData.COMMAND_ACTION.refresh_new_day, info, AppData.NO_MAIN_LOADING);
        }

        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }

    public static RemoteViews getRemoteView(Context context, DailyInfo info, String status){
        int layoutId = 0;
        if(info != null) layoutId = info._layout; 
        LayoutType layout = new LayoutType(context, layoutId);
        RemoteViews remoteView =  new RemoteViews(context.getPackageName(), layout._layoutId);
        return remoteView;
    }


    protected static void setControlEvent(Context context, RemoteViews remoteView, int appWidgetId) {
        Log.v(DailyPhotoData.TAG, "updateDisplayState: " + appWidgetId);
        // TODO set UI control event
        // setting button
        /*remoteView.setOnClickPendingIntent(
                R.id.bt_flickr_setting,
                setPendingIntent(context, Constants.COMMAND_ACTION.settings, appWidgetId, -1));*/
        // refresh list photo today
        remoteView.setOnClickPendingIntent(
                R.id.bt_flickr_setting,
                setPendingIntent(context, AppData.COMMAND_ACTION.load_today, appWidgetId, -1));
        // next day button
        remoteView.setOnClickPendingIntent(
                R.id.bt_flickr_next_day_refresh,
                setPendingIntent(context, AppData.COMMAND_ACTION.next_day, appWidgetId, -1));
        // prev day button
        remoteView.setOnClickPendingIntent(
                R.id.bt_flickr_prev_day_refresh,
                setPendingIntent(context, AppData.COMMAND_ACTION.prev_day, appWidgetId, -1));
        // next photos button
        remoteView.setOnClickPendingIntent(
                R.id.bt_flickr_next_photos_refresh,
                setPendingIntent(context, AppData.COMMAND_ACTION.next_page, appWidgetId, -1));
        // prev photos button
        remoteView.setOnClickPendingIntent(
                R.id.bt_flickr_prev_photos_refresh,
                setPendingIntent(context, AppData.COMMAND_ACTION.prev_page, appWidgetId, -1));
    }

    protected static PendingIntent setPendingIntent(Context context, AppData.COMMAND_ACTION action, int appWidgetId, int position) {
        Intent active = new Intent();		
        active.setAction(AppData.ACTION_WIDGET_CONTROL);
        active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

        Uri data = null;
        switch (action) {
        case refresh_main_view:
            data = Uri.withAppendedPath(
                    Uri.parse(AppData.URI_SCHEME + "://widget/id/#" + AppData.COMMAND_ACTION.refresh_main_view + "#" + position),
                    String.valueOf(appWidgetId));
            break;
        default:
            data = Uri.withAppendedPath(
                    Uri.parse(AppData.URI_SCHEME + "://widget/id/#" + action.name()),
                    String.valueOf(appWidgetId));
        }

        active.setData(data);

        return(PendingIntent.getBroadcast(context, 0, active, PendingIntent.FLAG_UPDATE_CURRENT));
    }

    public static void makeChangeLayoutType(Context context,  int appWidgetId) {
        Intent active = new Intent();		
        active.setAction(AppData.ACTION_WIDGET_CONTROL);
        active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);		

        Uri data = Uri.withAppendedPath(
                Uri.parse(AppData.URI_SCHEME + "://widget/id/#" + AppData.COMMAND_ACTION.change_layout),
                String.valueOf(appWidgetId));

        active.setData(data);
        context.sendBroadcast(active);
    }

    private  void startServiceUpdateAppWidget(Context context, int appWidgetId,
            AppData.COMMAND_ACTION action, DailyInfo info, int id){
        AppWidgetManager manager = AppWidgetManager.getInstance(context);

        RemoteViews remoteView = getRemoteView(context, info, null);

        // internet failed
        if(!ApplicationUtils.checkInternetConnection(context)) {
            remoteView.setTextViewText(R.id.tv_flickr_status_refresh, 
                    context.getResources().getString(R.string.connection_failed));
            // update provider
            ProviderUtils.updateWidgetInfoToProvider(context, info);
            // return;
        }

        if(id < 0){	
            remoteView.setTextViewText(R.id.tv_flickr_status_refresh, 
                    context.getResources().getString(R.string.loading));
        }else{
            remoteView.setTextViewText(R.id.tv_main_message_text_id, 
                    context.getResources().getString(R.string.loading));
        }

        manager.updateAppWidget(appWidgetId, remoteView);

        Log.d(DailyPhotoData.TAG, "updateAppWidget --> startService" +  info._page + " - " + id + " - " );
        // store pref

        Intent intent = new Intent(context, UpdateService.class);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        intent.putExtra(AppData.COMMAND_ACTION.refresh_main_view.name(), id);
        intent.putExtra(AppData.ACTION_NAME, action.name());
        context.startService(intent);
    }


    private void updateStatusWhenConnectionChange(Context context, String status){		
        DailyInfo info;

        AppWidgetManager manager = AppWidgetManager.getInstance(context);

        int[] appWidgetIds = manager.getAppWidgetIds(
                new ComponentName(context, DailyFlickrWidget.class));
        for(int appWidgetId : appWidgetIds){
            info = getWidgetInfo(context, appWidgetId);

            Log.i(DailyPhotoData.TAG, String.format("[updateStatusWhenConnectionChange = %s # %s] ", appWidgetId , status));
            RemoteViews remoteView = getRemoteView(context, info, status);
            remoteView.setTextViewText(R.id.tv_flickr_status_refresh , status);
            manager.updateAppWidget(appWidgetId, remoteView);
        }

        Log.i(DailyPhotoData.TAG, "[updateStatusWhenConnectionChange] " + appWidgetIds.length);
    }


    public static DailyInfo getWidgetInfo(Context context, int widgetId){
        if(sDailyInfos == null) return null;
        DailyInfo info_rs = sDailyInfos.get(widgetId);

        if(info_rs == null){
            info_rs = ProviderUtils.getWidgetInfoFromProvider(context, widgetId);
            sDailyInfos.put(widgetId, info_rs);	
        }

        return info_rs;
    }

    public static void restartWidgetInfo(Context context){
        if(sDailyInfos == null || sDailyInfos.size() == 0){
            AppWidgetManager manager = AppWidgetManager.getInstance(context);

            int[] appWidgetIds = manager.getAppWidgetIds(
                    new ComponentName(context, DailyFlickrWidget.class));

            for(int appWidgetId : appWidgetIds){
                DailyInfo info = ProviderUtils.getWidgetInfoFromProvider(context, appWidgetId);
                sDailyInfos.put(appWidgetId, info);
            }
        }
    }

    private void stopService(Context context){    	
        Intent intent = new Intent(context, UpdateService.class);		
        intent.putExtra("stop", true);
        context.startService(intent);
        Log.d(TAG, "updateAppWidget --> stopService" );
    }


    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (TextUtils.isEmpty(action))
            return;

        Log.d(TAG, "OnReceive:Action: " + action);
        if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)){
            Log.d(TAG, "OnReceive:Action: " + action);
        } else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
            final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
            ProviderUtils.deleteWidgetInfo(context, appWidgetId);

            stopService(context);
            this.onDeleted(context, new int[] { appWidgetId });
        }else if(AppData.ACTION_WIDGET_CONTROL.equals(action)){
            int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);

            // check internet connection 
            onHandleAction(context, intent.getData(), appWidgetId);

        } else {
            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {				
                Bundle b = intent.getExtras();
                Log.d(TAG, "OnReceive:Action: getExtras() " + b);
                if (b != null) {
                    NetworkInfo netInfo = (NetworkInfo) 
                            b.get(ConnectivityManager.EXTRA_NETWORK_INFO);
                    NetworkInfo.State state = netInfo.getState();

                    // NetworkInfo activeNetInfo = getActiveNetworkInfo();
                    Log.d(TAG, "OnReceive:Action: state " + state);
                    if (state == NetworkInfo.State.CONNECTED) {
                        updateStatusWhenConnectionChange(context, context.getResources().getString(R.string.loading));

                        Intent i = new Intent(context, UpdateService.class);	
                        i.putExtra(ConnectivityManager.CONNECTIVITY_ACTION, true);
                        context.startService(i);
                    }else{
                        updateStatusWhenConnectionChange(context, context.getResources().getString(R.string.connection_failed));
                    }
                }
            }else{

            }
        }
        super.onReceive(context, intent);
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        Log.d(TAG, "onDelete()");

        stopService(context);

        super.onDeleted(context, appWidgetIds);
    }

    @Override
    public void onDisabled(Context context) {
        Log.i(TAG, "onDisabled()" );
        // unregisterConectivityReceivers(context);
        stopService(context);
        super.onDisabled(context);
    }



    public void startServiceActivity(Context context, Class<?> cls, int appWidgetId){
        Intent intent = new Intent(context, cls);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_NO_HISTORY|Intent.FLAG_ACTIVITY_NO_ANIMATION);
        context.startActivity(intent);

    }

    public void onHandleAction(Context context, Uri data, int appWidgetId) {
        // TODO handle our action
        final String action = data.getFragment();
        if (TextUtils.isEmpty(action)) {
            return;
        }


        int position = AppData.NO_MAIN_LOADING;
        AppData.COMMAND_ACTION command = AppData.COMMAND_ACTION.refresh_new_day;

        if(action.contains(AppData.COMMAND_ACTION.refresh_main_view.name())){
            String[] actions = action.split("#");			
            if (actions.length > 1) {
                position = Integer.parseInt(actions[1]);	
            }
            command= AppData.COMMAND_ACTION.refresh_main_view;
        }else{
            command= AppData.COMMAND_ACTION.valueOf(action);
        }

        Log.i(TAG, "onHandleAction() . " + command.name() );

        DailyInfo info = getWidgetInfo(context, appWidgetId);

        switch (command) {
        case change_layout:
            RemoteViews remoteView = getRemoteView(context, info, null);

            setControlEvent(context, remoteView, appWidgetId);

            AppWidgetManager manager = AppWidgetManager.getInstance(context);
            manager.updateAppWidget(appWidgetId, remoteView);

            Intent intent = new Intent(context, UpdateService.class);	
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            intent.putExtra(AppData.ACTION_NAME, command.name());
            context.startService(intent);			
            return;

        case settings:
            startServiceActivity(context, DailyFlickrSettings.class, appWidgetId);
            return;

        case download_wallpaper:
            startServiceActivity(context, DailyImageDialog.class, appWidgetId);
            return;			

        case prev_day:			
            info._page = 1;
            info._date.add(Calendar.DATE, -1);
            break;

        case next_day:			
            if(! nextDay(info)) return;

            info._page = 1;
            info._date.add(Calendar.DATE, 1);

            break;

        case prev_page:			
            info._page = info._page - 1;
            if(info._page < 1) {
                info._page = DailyPhotoData.MAX_PAGE;
                info._date.add(Calendar.DATE, -1);
            }
            break;
        case next_page:

            if(info._page == DailyPhotoData.MAX_PAGE){
                if(!nextDay(info)) return;				
                info._page = 1;
                info._date.add(Calendar.DATE, 1);

            }else{
                info._page = info._page + 1;
            }

            break;
        case load_today:
            Calendar date = Calendar.getInstance(Locale.US);
            date.add(Calendar.DATE, -2);
            info._page = 1;
            info._date.setTime(date.getTime());
            break;
        default:
            break;
        }

        startServiceUpdateAppWidget(context, appWidgetId , 
                command , info, position);
    }


    private boolean nextDay(DailyInfo info){
        Calendar cal = info._date;
        Calendar now = Calendar.getInstance();
        long scale = now.getTimeInMillis() - cal.getTimeInMillis();
        long days = 2 * (24 * 60 * 60 * 1000);
        if( scale > days){
            return true;
        }

        now.setTime(cal.getTime());
        now.add(Calendar.DATE, 1);

        // no photos in day
        App.makeToastMessage("No photos on " 
                + ApplicationUtils.buildDateString(now.getTime()));

        return false;
    }
}
